<?php

class Soul_Template_Html_Form_Select extends Soul_Template_Html_Form_Input {

    private $_size = 1;	
    private $_multiple = FALSE;
    private $_groups = array();
    private $_labelFormat = NULL;
    private $_valueFormat = NULL;
    protected $options = array();    

    public function __construct() {
        $this->templateName = 'form/select';
        $this->addClass('input', 'select');
    }
    
    public function getLabelFormat(){
        return $this->_labelFormat;
    }
    
    public function setLabelFormat($value){
        $this->_labelFormat = $value;
        return $this;
    }
    
    public function getValueFormat(){
        return $this->_valueFormat;
    }
    
    public function setValueFormat($value){
        $this->_valueFormat = $value;
        return $this;
    }

    public function getSize() {
        return $this->_size;
    }

    public function setSize($value) {
        $this->_size = $value;
        return $this;
    }

    public function getMultiple() {
        return $this->_multiple;
    }

    public function setMultiple($value) {
        $this->_multiple = $value;
        return $this;
    }
    
    public function disableAllOptions(){
    	foreach($this->options as &$option){
    		$option['disabled'] = TRUE;
    	}
    	return $this;
    }
    
    public function enableAllOptions(){
    	foreach($this->options as &$option){
    		$option['disabled'] = FALSE;
    	}
    	return $this;    	
    }    

    public function clearOptions() {
        $this->options = array();
        return $this;
    }

    public function getOptions() {
        return $this->options;
    }

    public function setOption($label, $value, $disabled = FALSE, $attributes = array(), $group = NULL) {
        $option = array(
            'label' => $label,
            'value' => $value,
            'disabled' => $disabled,
            'attributes' => $attributes
        );
        if(is_null($group)){
        	$this->options[] = $option;
        }else{
        	if(!array_key_exists($group, $this->_groups)){
        		$this->_groups[$group] = array();
        	}
        	$this->_groups[$group][] = $option;
        }
        return $this;
    }

    public function addOption(array $values, $group = NULL) {
        foreach ($values as $key => $value) {
            $this->setOption($value, $key, NULL, NULL, $group);
        }
        return $this;
    }

    public function bindData($data, $labelKey = NULL, $valueKey = NULL) {
        if (!is_null($labelKey)) {
            $valueKey = is_null($valueKey) ? $labelKey : $valueKey;
            foreach ($data as $item) {
                $this->setOption($item[$labelKey], $item[$valueKey]);
            }
        } else {
            foreach ($data as $value => $label) {
                $this->setOption($label, $value);
            }
        }
        return $this;
    }
    
    protected function getFormatLabel($label){
        return empty($this->_labelFormat)?
                $label:
                sprintf($this->_labelFormat, $label);
    }
    
    protected function getFormatValue($value){
        return empty($this->_valueFormat)?
                $value:
                sprintf($this->_valueFormat, $value);
    }    

    protected function renderReadonly() {
        $result = '<span class="readonly">';
        $selectedValues = is_array($this->getValue()) ? $this->getValue() : array($this->getValue());
        if (!empty($selectedValues)) {
	        foreach ($this->options as $item) {
	        	foreach ($selectedValues as $sv) {
	                if (strlen($sv) == strlen($item['value']) && strcmp($sv, $item['value']) == 0) {
	                    $result .= $item['label'];
	                    break;
	                }
            	}	        	
	        }
	        foreach($this->_groups as $group=>$options){
	        	foreach($options as $item){
	        		foreach ($selectedValues as $sv) {
		        		if (strlen($sv) == strlen($item['value']) && strcmp($sv, $item['value']) == 0) {
		        			$result .= $item['label'];
		        			break;
		        		}
	        		}
	        	}
	        }
        }
        return $result . '</span>';
    }

    protected function renderEditable() {
        if (!$this->getEnabled()) {
            $this->addClass('disabled');
        }

        $this->setAttribute('id', $this->getId())
                ->setAttribute('name', $this->getName());
        if ($this->getSize() > 1) {
            $this->setAttribute('size', $this->getSize());
        }
        if (!$this->getEnabled()) {
            $this->setAttribute('disabled', 'disabled');
        }
        if ($this->getMultiple()) {
            $this->setAttribute('multiple', 'multiple');
        }

        $selectedValues = is_array($this->getValue()) ? $this->getValue() : array($this->getValue());

        $result = '<select ' . $this->getAttributeHtml() . '>';
        foreach ($this->options as $item) {
            $result .= $this->createOptionHtml($selectedValues, $item);
        }
        foreach($this->_groups as $group=>$options){
        	$result .= '<optgroup label="'.$group.'">';
        	foreach($options as $item){
        		$result .= $this->createOptionHtml($selectedValues, $item);
        	}
        	$result .= '</optgroup>';
        }
        return $result . '</select>';        
    }

    private function createOptionHtml($selectedValues, $option) {
        $selected = '';
        $disabled = '';
        $attribute = '';
        if (!empty($selectedValues)) {
            foreach ($selectedValues as $sv) {
                if (strlen($sv) == strlen($option['value']) && strcmp($sv, $option['value']) == 0) {
                    $selected = ' selected="selected"';
                }
            }
        }
        
        if (!empty($option['disabled'])) {
            $disabled = 'disabled="disabled"';
        }
        if (!empty($option['attributes']) && is_array($option['attributes'])) {
            $attribute = array();
            foreach ($option['attributes'] as $name => $value) {
                $attribute[] = $name . '="' . $value . '"';
            }
            $attribute = implode(' ', $attribute);
        }
        return sprintf('<option value="%s"%s%s%s>%s</option>', 
                $this->getFormatValue($option['value']), $selected, $disabled, $attribute, 
                $this->getFormatLabel($option['label']));
    }

}